#!/usr/bin/env python

import os
import subprocess
import unittest
import shutil
import rpm

class BasicIntegrationTest(unittest.TestCase):

    BASE_DIR = os.path.dirname(os.path.dirname(__file__))
    TEMP_DIR = os.path.join(BASE_DIR, 'target', 'tmp')


    def  setUp(self):
        if os.path.exists(self.TEMP_DIR):
            shutil.rmtree(self.TEMP_DIR)

    def test_building_simple_rpm(self):

        revision = '234'

        my_env = os.environ
        my_env['SVN_CMD'] = os.path.join(self.BASE_DIR, 'test/util/svn.py')
        my_env['SVNLOOK_CMD'] = os.path.join(self.BASE_DIR, 'test/util/svnlook.py')
        my_env['MKTEMP_CMD'] = os.path.join(self.BASE_DIR, 'test/util/mktemp.py')
        my_env['PARALLELISATION'] = '4'
        my_env['KEEPWORKDIR'] = '1'
        my_env['DEBUG'] = '1'
        cmd = os.path.join(self.BASE_DIR, 'config-rpm-maker')
        cmd_with_params = '%s %s %s' % (cmd, self.BASE_DIR, revision)

        self.execute(cmd_with_params, my_env)
        self.assertRpm('devweb01', revision)
        self.assertRpm('tuvweb03', revision)
        self.assertRpm('berweb01', revision,
                            requires = ['all-req', 'all-req2', 'ber-req', 'ber-req2', 'pro-req'],
                            provides = ['all-prov', 'all-prov2', 'all-prov3', 'pro-prov', 'pro-prov2'],
                            files={
                                'files/file_from_all' : '',
                                'files/file_from_ber' : '',
                                'files/file_from_pro' : '',
                                'files/override' : 'berweb',
                                'vars/override' : 'berweb',
                                'vars/var_in_var' : 'berwebberweb',
                            })


    def assertRpm(self, hostname, revision, requires = None, provides = None, files=None):
        path = os.path.join(self.TEMP_DIR, 'rpmbuild/RPMS/noarch', "is24-config-%s-21-%s.noarch.rpm" % (hostname, revision))
        self.assertTrue(os.path.exists(path), "Could not find file %s ." % path)
        ts = rpm.TransactionSet()
        ts.setVSFlags((rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS))
        f = open(path, 'r')
        try:
            hdr = ts.hdrFromFdno(f)
            del ts
            self.assertRequires(hdr, hostname, requires)
            self.assertProvides(hdr, hostname, provides)
        finally:
            f.close()

        extract_path = self.extractRpmFiles(path, hostname)
        self.assertFiles(files, extract_path)

    def assertFiles(self, files, extract_path):
        if files:
            for file_path in files:
                complete_path = os.path.join(extract_path, file_path)
                f = open(complete_path, 'r')
                try:
                    content = f.read()
                    self.assertEqual(content, files[file_path], "Content of '%s' differs:\nExpected: %s\nGot: %s" % (file_path, content, files[file_path]))
                finally:
                    f.close()


    def assertRequires(self, hdr, hostname, requires):
        if requires:
            real_requires = requires + ['hostname-' + hostname,'is24-config-' + hostname + '-repos', 'rpmlib(CompressedFileNames)', 'rpmlib(PayloadFilesHavePrefix)', 'yadt-client']
            self.assertArrayEqual(sorted(real_requires), sorted(hdr['requires']))

    def assertProvides(self, hdr, hostname, provides):
        if provides:
            real_provides = provides + ['is24-config-all', 'is24-config-' + hostname, ]
            self.assertArrayEqual(sorted(real_provides), sorted(hdr['provides']))

    def assertArrayEqual(self, expected, value):
        self.assertEqual(len(expected), len(value), "Lists have different element count. Expected %s , Got %s" % (str(expected), str(value)))
        for i in range(len(expected)):
            self.assertEqual(expected[i], value[i], "Element %d is different. Expected %s , Got %s" % (i, str(expected), str(value)))

    def extractRpmFiles(self, path, hostname):
        extract_path = os.path.join(self.TEMP_DIR, hostname + '.extract')
        os.mkdir(extract_path)

        p = subprocess.Popen('rpm2cpio ' + os.path.abspath(path) + ' | cpio  -idmv', shell=True, cwd=extract_path)
        p.communicate()

        return extract_path


    def execute(self, cmd_with_params, my_env):
        print "Executing %s" % cmd_with_params
        p = subprocess.Popen(cmd_with_params, env=my_env, cwd=self.BASE_DIR, shell=True)
        p.communicate()
        self.assertEqual(p.returncode, 0, "Process returned %d" % p.returncode)

if __name__ == '__main__':
    unittest.main()


